"""
知识库API路由
"""
from typing import Any, List, Optional, Dict
from fastapi import APIRouter, Depends, HTTPException, Query, Request, UploadFile, File, Form, status
from fastapi.responses import StreamingResponse, FileResponse
from motor.motor_asyncio import AsyncIOMotorDatabase
from pydantic import BaseModel, Field
import logging
from io import BytesIO

from app.api.deps import get_db, get_current_user
from app.core.response import success_response, error_response, paginated_response, ErrorTypes, ApiResponse
from app.schemas.knowledge import (
    KnowledgeFileCreate,
    KnowledgeFileUpdate,
    KnowledgeFileResponse,
    KnowledgeFolderCreate,
    KnowledgeFolderUpdate,
    KnowledgeFolderResponse,
    KnowledgeShareCreate,
    KnowledgeShareResponse,
    KnowledgeCommentCreate,
    KnowledgeCommentResponse,
    BatchDeleteRequest,
    KnowledgeStats
)
from app.services.knowledge_service import KnowledgeService

logger = logging.getLogger(__name__)

router = APIRouter()


class FileContentUpdate(BaseModel):
    """文件内容更新模型"""
    content: str = Field(..., description="文件内容")


# 初始化知识库服务实例
async def get_knowledge_service(db=Depends(get_db)):
    return KnowledgeService(db)


# ========== 文件管理API ==========

@router.post("/files/create", response_model=ApiResponse, summary="创建空文档")
async def create_empty_file(
    request: Request,
    file_data: KnowledgeFileCreate,
    format: Optional[str] = Query("txt", description="文件格式（txt, md, html等）"),
    current_user: dict = Depends(get_current_user),
    knowledge_service: KnowledgeService = Depends(get_knowledge_service)
):
    """创建空文档（文本类文件）"""
    try:
        result = await knowledge_service.create_empty_file(
            user=current_user,
            file_data=file_data,
            file_format=format or "txt"
        )
        
        return success_response(
            data=result.model_dump() if hasattr(result, 'model_dump') else result.dict(),
            message="创建文档成功",
            request_id=getattr(request.state, 'request_id', None) if hasattr(request, 'state') else None
        )
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"创建文档失败: {str(e)}", exc_info=True)
        return error_response(
            ErrorTypes.INTERNAL_ERROR,
            f"创建文档失败: {str(e)}",
            request_id=getattr(request.state, 'request_id', None) if hasattr(request, 'state') else None
        )


@router.post("/files/upload", response_model=ApiResponse, summary="上传文件")
async def upload_file(
    request: Request,
    file: UploadFile = File(...),
    title: Optional[str] = Form(None),
    description: Optional[str] = Form(None),
    folder_id: Optional[str] = Form(None),
    project_id: Optional[str] = Form(None),
    tags: Optional[str] = Form(None),  # 逗号分隔的标签字符串
    permission: Optional[str] = Form("private"),
    is_public: Optional[str] = Form("false"),
    current_user: dict = Depends(get_current_user),
    knowledge_service: KnowledgeService = Depends(get_knowledge_service)
):
    """上传文件到知识库"""
    try:
        # 如果没有提供标题，使用文件名（去掉扩展名）
        if not title and file.filename:
            from pathlib import Path
            title = Path(file.filename).stem
        
        if not title:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="文件标题不能为空"
            )
        
        # 解析标签
        tag_list = []
        if tags:
            tag_list = [tag.strip() for tag in tags.split(",") if tag.strip()]
        
        # 处理权限字段
        from app.models.knowledge import FilePermission
        try:
            permission_enum = FilePermission(permission) if permission else FilePermission.PRIVATE
        except ValueError:
            permission_enum = FilePermission.PRIVATE
        
        # 处理 is_public 字段（FormData 发送的是字符串）
        is_public_bool = False
        if isinstance(is_public, bool):
            is_public_bool = is_public
        elif isinstance(is_public, str):
            is_public_bool = is_public.lower() in ('true', '1', 'yes')
        elif is_public is not None:
            is_public_bool = bool(is_public)
        
        # 验证文件夹是否存在（如果指定了文件夹）
        if folder_id:
            try:
                folder_obj_id = knowledge_service._validate_object_id(folder_id, "文件夹ID")
                folder_exists = await knowledge_service.db.knowledge_folders.find_one({"_id": folder_obj_id})
                if not folder_exists:
                    raise HTTPException(
                        status_code=status.HTTP_400_BAD_REQUEST,
                        detail="选择的文件夹不存在，请重新选择文件夹或上传到根目录"
                    )
            except ValueError as e:
                raise HTTPException(
                    status_code=status.HTTP_400_BAD_REQUEST,
                    detail=f"无效的文件夹ID格式，请重新选择文件夹"
                )
        
        # 构建文件创建数据
        file_data = KnowledgeFileCreate(
            title=title,
            description=description,
            folder_id=folder_id,
            project_id=project_id,
            tags=tag_list,
            permission=permission_enum,
            is_public=is_public_bool
        )
        
        # 上传文件
        result = await knowledge_service.upload_file(
            user=current_user,
            file=file,
            file_data=file_data
        )
        
        return success_response(
            data=result.model_dump() if hasattr(result, 'model_dump') else result.dict(),
            message="文件上传成功",
            request_id=getattr(request.state, 'request_id', None) if hasattr(request, 'state') else None
        )
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"上传文件失败: {str(e)}", exc_info=True)
        return error_response(
            ErrorTypes.INTERNAL_ERROR,
            f"上传文件失败: {str(e)}",
            request_id=getattr(request.state, 'request_id', None) if hasattr(request, 'state') else None
        )


@router.get("/files", response_model=None, summary="获取文件列表")
async def get_files(
    request: Request,
    page: int = Query(1, ge=1, description="页码"),
    size: int = Query(20, ge=1, le=200, description="每页数量"),
    search: Optional[str] = Query(None, description="搜索关键词"),
    file_type: Optional[str] = Query(None, description="文件类型"),
    format: Optional[str] = Query(None, description="文件格式"),
    project_id: Optional[str] = Query(None, description="项目ID"),
    folder_id: Optional[str] = Query(None, description="文件夹ID"),
    tags: Optional[str] = Query(None, description="标签(逗号分隔)"),
    sort_by: Optional[str] = Query("created_at", description="排序字段"),
    sort_order: Optional[str] = Query("desc", regex="^(asc|desc)$", description="排序方向"),
    current_user: dict = Depends(get_current_user),
    knowledge_service: KnowledgeService = Depends(get_knowledge_service)
):
    """获取文件列表"""
    try:
        # 处理标签列表
        tag_list = None
        if tags:
            tag_list = [tag.strip() for tag in tags.split(",") if tag.strip()]
        
        # 调用服务层方法
        files, total = await knowledge_service.get_files(
            user=current_user,
            page=page,
            size=size,
            search=search,
            file_type=file_type,
            format=format,
            project_id=project_id,
            folder_id=folder_id,
            tags=tag_list,
            sort_by=sort_by or "created_at",
            sort_order=sort_order or "desc"
        )
        
        # 转换为字典格式
        file_list = [file.model_dump() if hasattr(file, 'model_dump') else file.dict() if hasattr(file, 'dict') else file for file in files]
        
        return paginated_response(
            items=file_list,
            total=total,
            page=page,
            size=size,
            message="获取文件列表成功",
            request_id=getattr(request.state, 'request_id', None) if hasattr(request, 'state') else None
        )
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"获取文件列表失败: {str(e)}", exc_info=True)
        return error_response(
            ErrorTypes.INTERNAL_ERROR,
            f"获取文件列表失败: {str(e)}",
            request_id=getattr(request.state, 'request_id', None) if hasattr(request, 'state') else None
        )


@router.get("/files/{file_id}", response_model=ApiResponse, summary="获取文件详情")
async def get_file(
    request: Request,
    file_id: str,
    current_user: dict = Depends(get_current_user),
    knowledge_service: KnowledgeService = Depends(get_knowledge_service)
):
    """获取文件详情"""
    try:
        file = await knowledge_service.get_file(user=current_user, file_id=file_id)
        
        # 增加查看次数
        await knowledge_service.increment_view_count(file_id)
        
        return success_response(
            data=file.model_dump() if hasattr(file, 'model_dump') else file.dict(),
            message="获取文件成功",
            request_id=getattr(request.state, 'request_id', None) if hasattr(request, 'state') else None
        )
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"获取文件失败: {str(e)}", exc_info=True)
        return error_response(
            ErrorTypes.INTERNAL_ERROR,
            f"获取文件失败: {str(e)}",
            request_id=getattr(request.state, 'request_id', None) if hasattr(request, 'state') else None
        )


@router.put("/files/{file_id}", response_model=ApiResponse, summary="更新文件信息")
async def update_file(
    request: Request,
    file_id: str,
    file_data: KnowledgeFileUpdate,
    current_user: dict = Depends(get_current_user),
    knowledge_service: KnowledgeService = Depends(get_knowledge_service)
):
    """更新文件信息"""
    try:
        result = await knowledge_service.update_file(
            user=current_user,
            file_id=file_id,
            file_data=file_data
        )
        
        return success_response(
            data=result.model_dump() if hasattr(result, 'model_dump') else result.dict(),
            message="更新文件成功",
            request_id=getattr(request.state, 'request_id', None) if hasattr(request, 'state') else None
        )
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"更新文件失败: {str(e)}", exc_info=True)
        return error_response(
            ErrorTypes.INTERNAL_ERROR,
            f"更新文件失败: {str(e)}",
            request_id=getattr(request.state, 'request_id', None) if hasattr(request, 'state') else None
        )


@router.delete("/files/{file_id}", response_model=ApiResponse, summary="删除文件")
async def delete_file(
    request: Request,
    file_id: str,
    current_user: dict = Depends(get_current_user),
    knowledge_service: KnowledgeService = Depends(get_knowledge_service)
):
    """删除文件"""
    try:
        await knowledge_service.delete_file(user=current_user, file_id=file_id)
        
        return success_response(
            data=None,
            message="删除文件成功",
            request_id=getattr(request.state, 'request_id', None) if hasattr(request, 'state') else None
        )
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"删除文件失败: {str(e)}", exc_info=True)
        return error_response(
            ErrorTypes.INTERNAL_ERROR,
            f"删除文件失败: {str(e)}",
            request_id=getattr(request.state, 'request_id', None) if hasattr(request, 'state') else None
        )


@router.post("/files/batch-delete", response_model=ApiResponse, summary="批量删除文件")
async def batch_delete_files(
    request: Request,
    batch_data: BatchDeleteRequest,
    current_user: dict = Depends(get_current_user),
    knowledge_service: KnowledgeService = Depends(get_knowledge_service)
):
    """批量删除文件"""
    try:
        result = await knowledge_service.batch_delete_files(
            user=current_user,
            file_ids=batch_data.ids
        )
        
        # 构建消息
        success_count = result.get("success_count", 0)
        fail_count = result.get("fail_count", 0)
        total_count = len(batch_data.ids)
        
        if fail_count == 0:
            message = f"成功删除 {success_count} 个文件"
        elif success_count == 0:
            message = f"删除失败：{result.get('errors', [])[0] if result.get('errors') else '未知错误'}"
        else:
            message = f"成功删除 {success_count} 个文件，{fail_count} 个文件删除失败"
        
        return success_response(
            data=result,
            message=message,
            request_id=getattr(request.state, 'request_id', None) if hasattr(request, 'state') else None
        )
    except Exception as e:
        logger.error(f"批量删除文件失败: {str(e)}", exc_info=True)
        return error_response(
            ErrorTypes.INTERNAL_ERROR,
            f"批量删除文件失败: {str(e)}",
            request_id=getattr(request.state, 'request_id', None) if hasattr(request, 'state') else None
        )


@router.get("/files/{file_id}/download", summary="下载文件")
async def download_file(
    file_id: str,
    current_user: dict = Depends(get_current_user),
    knowledge_service: KnowledgeService = Depends(get_knowledge_service)
):
    """下载文件"""
    try:
        from urllib.parse import quote
        
        file_data, mime_type, filename = await knowledge_service.download_file(
            user=current_user,
            file_id=file_id
        )
        
        # 处理中文文件名编码（RFC 5987 格式）
        try:
            # 尝试使用 ASCII 编码
            filename.encode('ascii')
            content_disposition = f'attachment; filename="{filename}"'
        except UnicodeEncodeError:
            # 如果包含非 ASCII 字符，使用 UTF-8 编码
            encoded_filename = quote(filename.encode('utf-8'), safe='')
            # 提供一个 ASCII 兼容的文件名作为备用
            safe_filename = filename.encode('ascii', 'ignore').decode('ascii') or 'file'
            content_disposition = f'attachment; filename="{safe_filename}"; filename*=UTF-8\'\'{encoded_filename}'
        
        return StreamingResponse(
            BytesIO(file_data),
            media_type=mime_type,
            headers={
                "Content-Disposition": content_disposition
            }
        )
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"下载文件失败: {str(e)}", exc_info=True)
        raise HTTPException(
            status_code=500,
            detail=f"下载文件失败: {str(e)}"
        )


@router.get("/files/{file_id}/content", response_model=ApiResponse, summary="获取文件内容")
async def get_file_content(
    request: Request,
    file_id: str,
    current_user: dict = Depends(get_current_user),
    knowledge_service: KnowledgeService = Depends(get_knowledge_service)
):
    """获取文件内容（仅支持文本类文件）"""
    try:
        content = await knowledge_service.get_file_content(
            user=current_user,
            file_id=file_id
        )
        
        return success_response(
            data={"content": content},
            message="获取文件内容成功",
            request_id=getattr(request.state, 'request_id', None) if hasattr(request, 'state') else None
        )
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"获取文件内容失败: {str(e)}", exc_info=True)
        return error_response(
            ErrorTypes.INTERNAL_ERROR,
            f"获取文件内容失败: {str(e)}",
            request_id=getattr(request.state, 'request_id', None) if hasattr(request, 'state') else None
        )


@router.put("/files/{file_id}/content", response_model=ApiResponse, summary="保存文件内容")
async def save_file_content(
    request: Request,
    file_id: str,
    content_data: FileContentUpdate,
    current_user: dict = Depends(get_current_user),
    knowledge_service: KnowledgeService = Depends(get_knowledge_service)
):
    """保存文件内容（仅支持文本类文件）"""
    try:
        result = await knowledge_service.save_file_content(
            user=current_user,
            file_id=file_id,
            content=content_data.content
        )
        
        return success_response(
            data=result.model_dump() if hasattr(result, 'model_dump') else result.dict(),
            message="保存文件内容成功",
            request_id=getattr(request.state, 'request_id', None) if hasattr(request, 'state') else None
        )
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"保存文件内容失败: {str(e)}", exc_info=True)
        return error_response(
            ErrorTypes.INTERNAL_ERROR,
            f"保存文件内容失败: {str(e)}",
            request_id=getattr(request.state, 'request_id', None) if hasattr(request, 'state') else None
        )


@router.get("/files/{file_id}/preview", summary="获取文件预览信息")
async def get_file_preview(
    request: Request,
    file_id: str,
    current_user: dict = Depends(get_current_user),
    knowledge_service: KnowledgeService = Depends(get_knowledge_service)
):
    """获取文件预览信息（返回预览URL、预览类型、是否可编辑等）"""
    try:
        from app.core.database import get_minio
        from app.core.config import settings
        from datetime import timedelta
        
        # 获取文件信息
        file = await knowledge_service.get_file(user=current_user, file_id=file_id)
        
        # 增加查看次数
        await knowledge_service.increment_view_count(file_id)
        
        # 生成MinIO预签名URL（7天有效期）
        minio_client = get_minio()
        preview_url = minio_client.presigned_get_object(
            settings.MINIO_BUCKET_NAME,
            file.file_path,
            expires=timedelta(days=7)
        )
        
        # 判断预览类型和是否可编辑
        # 确保 file.format 是字符串类型，并转换为小写
        file_format = str(file.format).lower().strip() if file.format else ""
        preview_type = "url"  # 默认使用URL预览
        is_editable = False
        
        # 记录文件格式用于调试
        logger.debug(f"文件格式: {file_format}, 文件ID: {file_id}")
        
        # 首先检查 Office 文件格式（优先级高于文本格式）
        # Excel表格预览
        if file_format in ["xls", "xlsx"]:
            preview_type = "excel"
        
        # Word文档预览
        elif file_format in ["doc", "docx"]:
            preview_type = "word"
        
        # PowerPoint预览
        elif file_format in ["ppt", "pptx"]:
            preview_type = "ppt"
        
        # PDF预览
        elif file_format == "pdf":
            preview_type = "pdf"
        
        # 图片预览
        elif file_format in ["jpg", "jpeg", "png", "gif", "bmp", "webp", "svg"]:
            preview_type = "image"
        
        # 可编辑的文本格式（放在最后，避免与 Office 格式冲突）
        elif file_format in ["txt", "md", "html", "json", "xml", "yaml", "yml", "csv"]:
            preview_type = "text"
            # 检查是否有编辑权限（只有创建者可以编辑）
            user_id = current_user.get("user_id") or current_user.get("id")
            is_editable = (file.author_id == user_id)
        
        # 视频预览
        elif file_format in ["mp4", "avi", "mov", "wmv"]:
            preview_type = "video"
        
        # 音频预览
        elif file_format in ["mp3", "wav", "ogg"]:
            preview_type = "audio"
        
        return success_response(
            data={
                "preview_url": preview_url,
                "preview_type": preview_type,
                "is_editable": is_editable,
                "file": file.model_dump() if hasattr(file, 'model_dump') else file.dict()
            },
            message="获取预览信息成功",
            request_id=getattr(request.state, 'request_id', None) if hasattr(request, 'state') else None
        )
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"获取预览信息失败: {str(e)}", exc_info=True)
        return error_response(
            ErrorTypes.INTERNAL_ERROR,
            f"获取预览信息失败: {str(e)}",
            request_id=getattr(request.state, 'request_id', None) if hasattr(request, 'state') else None
        )


# ========== 文件夹管理API ==========

@router.get("/folders", response_model=ApiResponse, summary="获取文件夹列表")
async def get_folders(
    request: Request,
    project_id: Optional[str] = Query(None, description="项目ID"),
    tree: bool = Query(False, description="是否返回树形结构"),
    current_user: dict = Depends(get_current_user),
    knowledge_service: KnowledgeService = Depends(get_knowledge_service)
):
    """获取文件夹列表"""
    try:
        folders = await knowledge_service.get_folders(
            user=current_user,
            project_id=project_id,
            tree=tree
        )
        
        folder_list = [folder.model_dump() if hasattr(folder, 'model_dump') else folder.dict() if hasattr(folder, 'dict') else folder for folder in folders]
        
        return success_response(
            data=folder_list,
            message="获取文件夹列表成功",
            request_id=getattr(request.state, 'request_id', None) if hasattr(request, 'state') else None
        )
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"获取文件夹列表失败: {str(e)}", exc_info=True)
        return error_response(
            ErrorTypes.INTERNAL_ERROR,
            f"获取文件夹列表失败: {str(e)}",
            request_id=getattr(request.state, 'request_id', None) if hasattr(request, 'state') else None
        )


@router.post("/folders", response_model=ApiResponse, summary="创建文件夹")
async def create_folder(
    request: Request,
    folder_data: KnowledgeFolderCreate,
    current_user: dict = Depends(get_current_user),
    knowledge_service: KnowledgeService = Depends(get_knowledge_service)
):
    """创建文件夹"""
    try:
        result = await knowledge_service.create_folder(
            user=current_user,
            folder_data=folder_data
        )
        
        return success_response(
            data=result.model_dump() if hasattr(result, 'model_dump') else result.dict(),
            message="创建文件夹成功",
            request_id=getattr(request.state, 'request_id', None) if hasattr(request, 'state') else None
        )
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"创建文件夹失败: {str(e)}", exc_info=True)
        return error_response(
            ErrorTypes.INTERNAL_ERROR,
            f"创建文件夹失败: {str(e)}",
            request_id=getattr(request.state, 'request_id', None) if hasattr(request, 'state') else None
        )


@router.put("/folders/{folder_id}", response_model=ApiResponse, summary="更新文件夹")
async def update_folder(
    request: Request,
    folder_id: str,
    folder_data: KnowledgeFolderUpdate,
    current_user: dict = Depends(get_current_user),
    knowledge_service: KnowledgeService = Depends(get_knowledge_service)
):
    """更新文件夹"""
    try:
        result = await knowledge_service.update_folder(
            user=current_user,
            folder_id=folder_id,
            folder_data=folder_data
        )
        
        return success_response(
            data=result.model_dump() if hasattr(result, 'model_dump') else result.dict(),
            message="更新文件夹成功",
            request_id=getattr(request.state, 'request_id', None) if hasattr(request, 'state') else None
        )
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"更新文件夹失败: {str(e)}", exc_info=True)
        return error_response(
            ErrorTypes.INTERNAL_ERROR,
            f"更新文件夹失败: {str(e)}",
            request_id=getattr(request.state, 'request_id', None) if hasattr(request, 'state') else None
        )


@router.delete("/folders/{folder_id}", response_model=ApiResponse, summary="删除文件夹")
async def delete_folder(
    request: Request,
    folder_id: str,
    current_user: dict = Depends(get_current_user),
    knowledge_service: KnowledgeService = Depends(get_knowledge_service)
):
    """删除文件夹"""
    try:
        await knowledge_service.delete_folder(user=current_user, folder_id=folder_id)
        
        return success_response(
            data=None,
            message="删除文件夹成功",
            request_id=getattr(request.state, 'request_id', None) if hasattr(request, 'state') else None
        )
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"删除文件夹失败: {str(e)}", exc_info=True)
        return error_response(
            ErrorTypes.INTERNAL_ERROR,
            f"删除文件夹失败: {str(e)}",
            request_id=getattr(request.state, 'request_id', None) if hasattr(request, 'state') else None
        )


# ========== 分享功能API ==========

@router.post("/files/{file_id}/share", response_model=ApiResponse, summary="创建文件分享链接")
async def create_share(
    request: Request,
    file_id: str,
    share_data: KnowledgeShareCreate,
    current_user: dict = Depends(get_current_user),
    knowledge_service: KnowledgeService = Depends(get_knowledge_service)
):
    """创建文件分享链接"""
    try:
        result = await knowledge_service.create_share(
            user=current_user,
            file_id=file_id,
            share_data=share_data
        )
        
        return success_response(
            data=result.model_dump() if hasattr(result, 'model_dump') else result.dict(),
            message="创建分享链接成功",
            request_id=getattr(request.state, 'request_id', None) if hasattr(request, 'state') else None
        )
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"创建分享链接失败: {str(e)}", exc_info=True)
        return error_response(
            ErrorTypes.INTERNAL_ERROR,
            f"创建分享链接失败: {str(e)}",
            request_id=getattr(request.state, 'request_id', None) if hasattr(request, 'state') else None
        )


@router.get("/files/{file_id}/share", response_model=ApiResponse, summary="获取文件分享信息")
async def get_share(
    request: Request,
    file_id: str,
    current_user: dict = Depends(get_current_user),
    knowledge_service: KnowledgeService = Depends(get_knowledge_service)
):
    """获取文件分享信息"""
    try:
        result = await knowledge_service.get_share(user=current_user, file_id=file_id)
        
        return success_response(
            data=result.model_dump() if result and hasattr(result, 'model_dump') else result.dict() if result else None,
            message="获取分享信息成功",
            request_id=getattr(request.state, 'request_id', None) if hasattr(request, 'state') else None
        )
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"获取分享信息失败: {str(e)}", exc_info=True)
        return error_response(
            ErrorTypes.INTERNAL_ERROR,
            f"获取分享信息失败: {str(e)}",
            request_id=getattr(request.state, 'request_id', None) if hasattr(request, 'state') else None
        )


@router.delete("/files/{file_id}/share", response_model=ApiResponse, summary="撤销文件分享链接")
async def revoke_share(
    request: Request,
    file_id: str,
    current_user: dict = Depends(get_current_user),
    knowledge_service: KnowledgeService = Depends(get_knowledge_service)
):
    """撤销文件分享链接"""
    try:
        await knowledge_service.revoke_share(user=current_user, file_id=file_id)
        
        return success_response(
            data=None,
            message="撤销分享链接成功",
            request_id=getattr(request.state, 'request_id', None) if hasattr(request, 'state') else None
        )
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"撤销分享链接失败: {str(e)}", exc_info=True)
        return error_response(
            ErrorTypes.INTERNAL_ERROR,
            f"撤销分享链接失败: {str(e)}",
            request_id=getattr(request.state, 'request_id', None) if hasattr(request, 'state') else None
        )


@router.get("/share/{token}", response_model=ApiResponse, summary="通过分享令牌访问文件")
async def get_file_by_share_token(
    request: Request,
    token: str,
    password: Optional[str] = Query(None, description="分享密码"),
    knowledge_service: KnowledgeService = Depends(get_knowledge_service)
):
    """通过分享令牌访问文件（公开接口，不需要登录）"""
    try:
        file_resp, share_resp = await knowledge_service.get_file_by_share_token(token=token, password=password)
        
        from app.schemas.knowledge import KnowledgeShareAccessResponse
        access_resp = KnowledgeShareAccessResponse(
            file=file_resp,
            share=share_resp
        )
        
        return success_response(
            data=access_resp.model_dump() if hasattr(access_resp, 'model_dump') else access_resp.dict(),
            message="获取文件成功",
            request_id=getattr(request.state, 'request_id', None) if hasattr(request, 'state') else None
        )
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"通过分享令牌获取文件失败: {str(e)}", exc_info=True)
        return error_response(
            ErrorTypes.INTERNAL_ERROR,
            f"获取文件失败: {str(e)}",
            request_id=getattr(request.state, 'request_id', None) if hasattr(request, 'state') else None
        )


@router.get("/share/{token}/download", summary="通过分享令牌下载文件")
async def download_file_by_share_token(
    token: str,
    password: Optional[str] = Query(None, description="分享密码"),
    knowledge_service: KnowledgeService = Depends(get_knowledge_service)
):
    """通过分享令牌下载文件（公开接口，不需要登录）"""
    try:
        from urllib.parse import quote
        from io import BytesIO
        
        # 验证分享令牌并获取文件信息
        file_resp, share_resp = await knowledge_service.get_file_by_share_token(token=token, password=password)
        
        # 检查是否允许下载
        if not share_resp.allow_download:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="此分享链接不允许下载"
            )
        
        # 下载文件
        file_data, mime_type, filename = await knowledge_service.download_file_by_share_token(token=token, password=password)
        
        # 处理中文文件名编码（RFC 5987 格式）
        try:
            filename.encode('ascii')
            content_disposition = f'attachment; filename="{filename}"'
        except UnicodeEncodeError:
            encoded_filename = quote(filename.encode('utf-8'), safe='')
            safe_filename = filename.encode('ascii', 'ignore').decode('ascii') or 'file'
            content_disposition = f'attachment; filename="{safe_filename}"; filename*=UTF-8\'\'{encoded_filename}'
        
        return StreamingResponse(
            BytesIO(file_data),
            media_type=mime_type,
            headers={
                "Content-Disposition": content_disposition
            }
        )
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"通过分享令牌下载文件失败: {str(e)}", exc_info=True)
        raise HTTPException(
            status_code=500,
            detail=f"下载文件失败: {str(e)}"
        )


# ========== 评论功能API ==========

@router.post("/files/{file_id}/comments", response_model=ApiResponse, summary="添加文件评论")
async def create_comment(
    request: Request,
    file_id: str,
    comment_data: KnowledgeCommentCreate,
    current_user: dict = Depends(get_current_user),
    knowledge_service: KnowledgeService = Depends(get_knowledge_service)
):
    """添加文件评论"""
    try:
        result = await knowledge_service.create_comment(
            user=current_user,
            file_id=file_id,
            comment_data=comment_data
        )
        
        return success_response(
            data=result.model_dump() if hasattr(result, 'model_dump') else result.dict(),
            message="添加评论成功",
            request_id=getattr(request.state, 'request_id', None) if hasattr(request, 'state') else None
        )
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"添加评论失败: {str(e)}", exc_info=True)
        return error_response(
            ErrorTypes.INTERNAL_ERROR,
            f"添加评论失败: {str(e)}",
            request_id=getattr(request.state, 'request_id', None) if hasattr(request, 'state') else None
        )


@router.get("/files/{file_id}/comments", response_model=ApiResponse, summary="获取文件评论列表")
async def get_comments(
    request: Request,
    file_id: str,
    knowledge_service: KnowledgeService = Depends(get_knowledge_service)
):
    """获取文件评论列表"""
    try:
        comments = await knowledge_service.get_comments(file_id=file_id)
        
        comment_list = [comment.model_dump() if hasattr(comment, 'model_dump') else comment.dict() for comment in comments]
        
        return success_response(
            data=comment_list,
            message="获取评论列表成功",
            request_id=getattr(request.state, 'request_id', None) if hasattr(request, 'state') else None
        )
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"获取评论列表失败: {str(e)}", exc_info=True)
        return error_response(
            ErrorTypes.INTERNAL_ERROR,
            f"获取评论列表失败: {str(e)}",
            request_id=getattr(request.state, 'request_id', None) if hasattr(request, 'state') else None
        )


# ========== 收藏功能API ==========

@router.post("/files/{file_id}/favorite", response_model=ApiResponse, summary="收藏文件")
async def favorite_file(
    request: Request,
    file_id: str,
    current_user: dict = Depends(get_current_user),
    knowledge_service: KnowledgeService = Depends(get_knowledge_service)
):
    """收藏文件"""
    try:
        await knowledge_service.favorite_file(user=current_user, file_id=file_id)
        
        return success_response(
            data=None,
            message="收藏成功",
            request_id=getattr(request.state, 'request_id', None) if hasattr(request, 'state') else None
        )
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"收藏文件失败: {str(e)}", exc_info=True)
        return error_response(
            ErrorTypes.INTERNAL_ERROR,
            f"收藏文件失败: {str(e)}",
            request_id=getattr(request.state, 'request_id', None) if hasattr(request, 'state') else None
        )


@router.delete("/files/{file_id}/favorite", response_model=ApiResponse, summary="取消收藏文件")
async def unfavorite_file(
    request: Request,
    file_id: str,
    current_user: dict = Depends(get_current_user),
    knowledge_service: KnowledgeService = Depends(get_knowledge_service)
):
    """取消收藏文件"""
    try:
        await knowledge_service.unfavorite_file(user=current_user, file_id=file_id)
        
        return success_response(
            data=None,
            message="取消收藏成功",
            request_id=getattr(request.state, 'request_id', None) if hasattr(request, 'state') else None
        )
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"取消收藏失败: {str(e)}", exc_info=True)
        return error_response(
            ErrorTypes.INTERNAL_ERROR,
            f"取消收藏失败: {str(e)}",
            request_id=getattr(request.state, 'request_id', None) if hasattr(request, 'state') else None
        )


@router.get("/files/favorites", response_model=None, summary="获取收藏的文件列表")
async def get_favorite_files(
    request: Request,
    page: int = Query(1, ge=1, description="页码"),
    size: int = Query(20, ge=1, le=200, description="每页数量"),
    current_user: dict = Depends(get_current_user),
    knowledge_service: KnowledgeService = Depends(get_knowledge_service)
):
    """获取收藏的文件列表"""
    try:
        files, total = await knowledge_service.get_favorite_files(
            user=current_user,
            page=page,
            size=size
        )
        
        file_list = [file.model_dump() if hasattr(file, 'model_dump') else file.dict() for file in files]
        
        return paginated_response(
            items=file_list,
            total=total,
            page=page,
            size=size,
            message="获取收藏列表成功",
            request_id=getattr(request.state, 'request_id', None) if hasattr(request, 'state') else None
        )
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"获取收藏列表失败: {str(e)}", exc_info=True)
        return error_response(
            ErrorTypes.INTERNAL_ERROR,
            f"获取收藏列表失败: {str(e)}",
            request_id=getattr(request.state, 'request_id', None) if hasattr(request, 'state') else None
        )


# ========== 统计信息API ==========

@router.get("/stats", response_model=ApiResponse, summary="获取知识库统计信息")
async def get_knowledge_stats(
    request: Request,
    project_id: Optional[str] = Query(None, description="项目ID"),
    current_user: dict = Depends(get_current_user),
    db: AsyncIOMotorDatabase = Depends(get_db),
    knowledge_service: KnowledgeService = Depends(get_knowledge_service)
):
    """获取知识库统计信息"""
    try:
        from bson import ObjectId
        from app.utils.state_utils import get_state_code_by_name_keywords
        
        user_id = ObjectId(current_user["id"])
        
        # 从状态管理系统动态获取"已删除"状态代码并过滤（使用 knowledge_service 的辅助方法）
        deleted_status_code = await knowledge_service._get_deleted_status_code()
        
        # 构建查询条件
        query: Dict[str, Any] = {}
        if deleted_status_code:
            query["status"] = {"$ne": deleted_status_code}
        
        if project_id:
            query["project_id"] = knowledge_service._validate_object_id(project_id, "项目ID")
        
        # 权限筛选
        permission_conditions = [
            {"is_public": True},
            {"permission": "public"},
            {"permission": "team"},
            {"author_id": user_id}
        ]
        query["$or"] = permission_conditions
        
        # 统计总数
        total_files = await knowledge_service.db.knowledge_files.count_documents(query)
        
        # 统计文件夹数
        folder_query: Dict[str, Any] = {}
        if project_id:
            folder_query["project_id"] = knowledge_service._validate_object_id(project_id, "项目ID")
        total_folders = await knowledge_service.db.knowledge_folders.count_documents(folder_query)
        
        # 统计总大小
        pipeline = [
            {"$match": query},
            {"$group": {"_id": None, "total_size": {"$sum": "$file_size"}}}
        ]
        size_result = await knowledge_service.db.knowledge_files.aggregate(pipeline).to_list(1)
        total_size = size_result[0]["total_size"] if size_result else 0
        
        # 按类型统计
        type_pipeline = [
            {"$match": query},
            {"$group": {"_id": "$file_type", "count": {"$sum": 1}}}
        ]
        type_results = await knowledge_service.db.knowledge_files.aggregate(type_pipeline).to_list(100)
        files_by_type = {item["_id"]: item["count"] for item in type_results}
        
        # 按格式统计
        format_pipeline = [
            {"$match": query},
            {"$group": {"_id": "$format", "count": {"$sum": 1}}}
        ]
        format_results = await knowledge_service.db.knowledge_files.aggregate(format_pipeline).to_list(100)
        files_by_format = {item["_id"]: item["count"] for item in format_results}
        
        # 最近文件
        recent_files_cursor = knowledge_service.db.knowledge_files.find(query).sort("created_at", -1).limit(10)
        recent_files = []
        async for file_doc in recent_files_cursor:
            recent_files.append({
                "id": str(file_doc["_id"]),
                "title": file_doc.get("title", ""),
                "filename": file_doc.get("filename", ""),
                "file_size": file_doc.get("file_size", 0),
                "file_type": file_doc.get("file_type", ""),
                "format": file_doc.get("format", ""),
                "created_at": file_doc.get("created_at").isoformat() if file_doc.get("created_at") else None
            })
        
        # 热门文件（按查看次数）
        popular_files_cursor = knowledge_service.db.knowledge_files.find(query).sort("view_count", -1).limit(10)
        popular_files = []
        async for file_doc in popular_files_cursor:
            popular_files.append({
                "id": str(file_doc["_id"]),
                "title": file_doc.get("title", ""),
                "filename": file_doc.get("filename", ""),
                "file_size": file_doc.get("file_size", 0),
                "file_type": file_doc.get("file_type", ""),
                "format": file_doc.get("format", ""),
                "created_at": file_doc.get("created_at").isoformat() if file_doc.get("created_at") else None
            })
        
        stats = {
            "total_files": total_files,
            "total_folders": total_folders,
            "total_size": total_size,
            "files_by_type": files_by_type,
            "files_by_format": files_by_format,
            "recent_files": recent_files,
            "popular_files": popular_files
        }
        
        return success_response(
            data=stats,
            message="获取统计信息成功",
            request_id=getattr(request.state, 'request_id', None) if hasattr(request, 'state') else None
        )
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"获取统计信息失败: {str(e)}", exc_info=True)
        return error_response(
            ErrorTypes.INTERNAL_ERROR,
            f"获取统计信息失败: {str(e)}",
            request_id=getattr(request.state, 'request_id', None) if hasattr(request, 'state') else None
        )

